#pragma once
#include "precompiled.h"

namespace IcyCrystal {
	class Quad;
	class Arg;
	class Register;
	struct UseInfo;

	typedef vector<Quad*> ArgList;
	typedef vector<Register*> RegisterList;
	typedef vector<Arg*> LocationList;
	typedef map<string*,UseInfo> UseMap;

	struct UseInfo{
		int lastUse;
	};

	enum GlobalType {
		INT, FLOAT, STRING, ARRAY,
		LABEL, SYMBOL, POINTER
	};


	enum OpType {
		GLOBAL_DECL,
		PUSH, POP,
		MOV,
		SUB, ADD, MULT, DIV,
		RETURN,

		BLOCK
	};

	enum ArgType{
		EBP, ESP,
		REGISTER, VIRTUAL_REGISTER, STACK, GLOBAL, EBP_OFFSET,
		INT_CONSTANT, FLOAT_CONSTANT,
		TEMP,
		LOCAL, CONSTANT,
		NONE
	};

	class GlobalDeclaration {
	public:
		GlobalType globalType;
		string* symbolName;

		union{
			int intValue;
			float floatValue;
			string* stringValue;
			
			vector<GlobalDeclaration>* arrayValue;
		} value;

	};

	class Arg{
	public:
		ArgType arg;

		union {
			string* symbolName;
			int intName;
		} name;
	};

	class Quad {
	public:

		Quad(){
			inner.normalOp.result.arg = NONE;
			statementNumber = 0;
		}
		OpType op;
		int statementNumber;

		union {
			struct {
				Arg arg1;
				Arg arg2;
				
				Arg result;
			} normalOp;

			GlobalDeclaration declaration;
			ArgList* blockChildren;
		} inner;

	};

	class Register {
	public:
		Register(){
			variables = new SymbolList;
		}
		string registerName;

		// List of variables the register contains.
		SymbolList* variables;
	};

	
}
